package start;
/**
 * This class implements a separate application (server process)
 * handles the LIST, ADD and REMOVE commands
 * list of peers is stored in memory only
 */

import java.io.*;
import java.net.*;
import java.util.*;

import xchange.Debug;

public class NameServer {

    private String ip = "";
    private final int port = 9001;
    private ArrayList<String> list;

    BufferedReader in;
    PrintWriter out;
 
    public NameServer() {
        list = new ArrayList<String>();
	if (Debug.DEBUG) {
	    System.out.println("Nameserver started ...");
	}
	try {
	    listenAndHandle();
	}
	catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /**
     * create and listen on server socket
     *
     */

    public void listenAndHandle() throws Exception {
        ServerSocket ss = new ServerSocket(port);

	// listen for incoming connections
	// todo: make Nameserver multi-threaded, i.e. a new thread for each incoming client
	while (true) {
	    Socket cs = ss.accept();
	    // handle a single request
	    handle(cs);
	    // close client socket and resume listening
	    cs.close();
	}
    }

    /**
     * handle incoming messages
     * all messages are strings ending on "\n"
     */
    private void handle(Socket s) throws Exception {
	// get socket input stream and open a BufferedReader on it
	in = new BufferedReader(new InputStreamReader(s.getInputStream()));

	// get socket output stream and open a PrintWriter on it
	out = new PrintWriter(s.getOutputStream(), true);
        
	// get the message
        String line = null;
	do {
	    line = in.readLine();
	} while (line == null);

	if (line.startsWith("ADD")) {
            handleAdd(line);
        }

        else if (line.startsWith("REMOVE")) {
            handleRemove(line);
        }

        else if (line.startsWith("LIST")) {
            handleList();
        }

        else {
            handleError();
        }
    }


    private void handleAdd(String line) throws Exception {
	if (Debug.DEBUG) {
	    System.out.println("Nameserver received : " + line);
	}
        String[] s = line.split(" ");
        if (s.length != 2) {
            handleError();
            return;
        }
        String ip = s[1];
        if (!list.contains(ip)) {
            list.add(ip);
        } else {
	    if (Debug.DEBUG) {
		System.out.println("Nameserver : duplicate ip : " + ip);
	    }
	}

        out.println("OK");
	if (Debug.DEBUG) {
	    System.out.println("Nameserver : added " + ip);
	}
    }

    private void handleRemove(String line) throws Exception {
        String[] s = line.split(" ");
        if (s.length != 2) {
            handleError();
            return;
        }
        String ip = s[1];
        list.remove(ip);
        out.println("OK");
	if (Debug.DEBUG) {
	    System.out.println("Nameserver : removed " + ip);
	}
    }

    private void handleList() throws Exception {
	if (Debug.DEBUG) {
	    System.out.println("Nameserver received LIST request");
	}
	for (String ip : list) {
            out.print(ip + " ");
        }
	// send EOL
        out.println();
    }

    private void handleError() throws Exception {
        out.println("FAIL");
    }

    public static void main(String[] args) throws Exception {
        new NameServer();
    }
}
